package model;

import java.util.ArrayList;

public class ChessGame {
	
	private int WHITE_TO_MOVE = 0;
	//private int BLACK_TO_MOVE = 1;
	
	private Board board;
	
	private Player player1; // White player
	private Player player2; // Black player
	
	private Square moveStartSquare = Square.OUT_OF_RANGE;
	private Square moveEndSquare = Square.OUT_OF_RANGE;
	
	/*
	public ChessGame() {
		initGame();
	}*/
	
	public Board getBoard() {
		return board;
	}

	public void initGame() {
		board = new Board();
		board.initBoard();
		
		// ***DEBUG***
		//debugSetCheckPosition();
		//debugSetCheckmatePosition();
		//debugSetTobeCheckmatePosition(); 
		//debugSetStalematePosition();
		// ***********
		
		// Test HUMAN vs HUMAN
		player1 = new Player(PlayerType.HUMAN, BrainMode.DEPTH_MODE, 5);
		player2 = new Player(PlayerType.HUMAN, BrainMode.DEPTH_MODE, 5);
		
		// Test HUMAN vs MACHINE lvl 2
		//player1 = new Player(PlayerType.HUMAN, BrainMode.DEPTH_MODE, 3);
		//player2 = new Player(PlayerType.MACHINE, BrainMode.DEPTH_MODE, 3);
		//player2 = new Player(PlayerType.MACHINE, BrainMode.TIME_MODE, 5000);
		
		//Test MACHINE lvl 2 vs MACHINE lvl 2
		//player1 = new Player(PlayerType.MACHINE, BrainMode.DEPTH_MODE, 2);
		//player2 = new Player(PlayerType.MACHINE, BrainMode.DEPTH_MODE, 5);
				
		
		moveStartSquare = Square.OUT_OF_RANGE;
		moveEndSquare = Square.OUT_OF_RANGE;
	}

	/**
	 * Get human player action
	 * @param square
	 */
	public void HumanPlayerAction(Square square) {

		// TODO move this code to a dedicated game loop
		if (Engine.isCheckmate(board)) {
			// Game over: no more input taken in account
			System.out.println("CHECKMATE!");
		} else
		if (Engine.isStalemate(board)) {
			// Game over: no more input taken in account
			System.out.println("STALEMATE!");
		} else {
			if(Engine.isCheck(board)){
				System.out.println("CHECK!");
			}

			if (getCurrentPlayer().getPlayerType() == PlayerType.HUMAN) {

				if (moveStartSquare == Square.OUT_OF_RANGE
						&& moveEndSquare == Square.OUT_OF_RANGE) {
					moveStartSquare = square;
					debugDisplayLegalMove(board);
				}
				// second square input
				else if (moveStartSquare != Square.OUT_OF_RANGE
						&& moveEndSquare == Square.OUT_OF_RANGE) {
					moveEndSquare = square;
				}

				if (moveStartSquare != Square.OUT_OF_RANGE
						&& moveEndSquare != Square.OUT_OF_RANGE) {
					// Play move
					if (moveStartSquare != moveEndSquare) {
						if (board.isPiecePlayable(moveStartSquare)) {
							Move currentMove = new Move(moveStartSquare,
									moveEndSquare);
							System.out.println("input move: "
									+ currentMove.toString());
							if (Engine.isLegalMove(board, currentMove)) {
								getCurrentPlayer().playAsHuman(board, currentMove);
							}
						}
					}
					moveStartSquare = Square.OUT_OF_RANGE;
					moveEndSquare = Square.OUT_OF_RANGE;
				}
			}
/*
			if (getCurrentPlayer().getPlayerType() == PlayerType.MACHINE) {
				try {
					getCurrentPlayer().Play(board);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			*/
		}
	}
	
	
	/**
	 * ***DEBUG FUNCTION***
	 * Display all legal moves for the given board
	 * @param board
	 */
	private void debugDisplayLegalMove(Board board) {
		
		ArrayList<Move> legalMoves = Engine.getLegalMoves(board);
		// DEBUG ------------------
		System.out.println("Possible moves:");
		for(Move m : legalMoves){System.out.print(m.toString() + " ");}
		System.out.println();
		//-------------------------
		System.out.println("nb of possible moves: " + legalMoves.size());
		return;
	}

	/**
	 * Get the content of a given square
	 * 
	 * @param square
	 * @return
	 */
	public Piece getPiece(int index) {
		return board.getPiece(index);
	}

	/**
	 * Indicates if the piece is playable for the given player (only check the
	 * color)
	 * 
	 * @param square
	 * @return
	 */
	public boolean isPiecePlayable(Square square) {
		return board.isPiecePlayable(square);
	}

	public Player getCurrentPlayer() {
		if(board.getTurn() == WHITE_TO_MOVE){
			return player1;
		} else {
			return player2;
		}
	}
	
	/**
	 * *** DEBUG ***
	 * set check position for blacks 
	 */
	public void debugSetCheckPosition() {
		for(int i=0;i<64;i++){
			board.setPiece(Piece.EMPTY, Square.get(i));
		}
		board.setPiece(Piece.WK,Square.A1);
		board.setPiece(Piece.WR,Square.B2);
		board.setPiece(Piece.BK,Square.A8);
		board.setWhiteToMove();
	}
	/**
	 * *** DEBUG ***
	 * set check position for blacks 
	 */
	public void debugSetCheckmatePosition() {
		for(int i=0;i<64;i++){
			board.setPiece(Piece.EMPTY, Square.get(i));
		}
		board.setPiece(Piece.WR,Square.A8);
		board.setPiece(Piece.WK,Square.E7);
		board.setPiece(Piece.BK,Square.E8);
		board.setBlackToMove();
	}
	/**
	 * *** DEBUG ***
	 * set check position for blacks 
	 */
	public void debugSetTobeCheckmatePosition() {
		for(int i=0;i<64;i++){
			board.setPiece(Piece.EMPTY, Square.get(i));
		}
		board.setPiece(Piece.WR,Square.A7);
		board.setPiece(Piece.WK,Square.E7);
		board.setPiece(Piece.BK,Square.E8);
		board.setWhiteToMove();
	}
	/**
	 * *** DEBUG ***
	 * set check position for blacks 
	 */
	public void debugSetStalematePosition() {
		for(int i=0;i<64;i++){
			board.setPiece(Piece.EMPTY, Square.get(i));
		}
		board.setPiece(Piece.WR,Square.A7);
		board.setPiece(Piece.WK,Square.F8);
		board.setPiece(Piece.BK,Square.H8);
		board.setBlackToMove();
	}
	
}
